<?php
/**
 * Created by PhpStorm.
 * User: zhangjincheng
 * Date: 17-8-14
 * Time: 下午2:55
 */

namespace WsdServer\Components\Consul;

use Server\Components\Consul\ConsulHelp;
use Server\Components\Consul\ConsulProcess;

use Server\CoreBase\PortManager;

class WsdConsulProcess extends ConsulProcess
{
    /**
     * @param $process
     * @throws SwooleException
     */
    public function start($process)
    {
        $this->jsonFormatHandler();

        $consul_agent_addr = getenv("SD_CONSUL_AGENT_ADDR");
        if (empty($consul_agent_addr)) {
            $consul_agent_addr = $this->config['consul']['agent_addr'];
        }
        if (empty($consul_agent_addr)) {
            $consul_agent_addr = "127.0.0.1";
        }
        if ($consul_agent_addr == '127.0.0.1'){     // 启用内置consul
            if (!is_file(BIN_DIR . "/exec/consul")) {
                secho("[CONSUL]", "consul没有安装,请下载最新的consul安装至bin/exec目录,或者在config/consul.php中取消使能");
                get_instance()->server->shutdown();
                exit();
            }

            $this->exec(BIN_DIR . "/exec/consul", ['agent', '-ui', '-config-dir', BIN_DIR . '/exec/consul.d']);
        }
    }

    /**
     * 格式化consul模板，输出配置文件
     */
    public function jsonFormatHandler()
    {
        // 如果非扩展模式，则调用父类方法返回
        $extent_mode = $this->config->get('consul.extent_mode',false);
        if (!$extent_mode){
            return parent::jsonFormatHandler();
        }

        $config = get_instance()->config->get('consul');
        if (isset($config['datacenter'])) {
            $newConfig['datacenter'] = $config['datacenter'];
        }
        if (isset($config['client_addr'])) {
            $newConfig['client_addr'] = $config['client_addr'];
        }
        $newConfig['node_name'] = getNodeName();
        $newConfig['start_join'] = $config['start_join'];
        $newConfig['data_dir'] = $config['data_dir'];

        // Modify by hb on 2017-12-25: Consul-Agent连接配置
        $consul_agent_addr = getenv("SD_CONSUL_AGENT_ADDR");
        if (empty($consul_agent_addr)) {
            $consul_agent_addr = $config['agent_addr'];
        }
        if (empty($consul_agent_addr)) {
            $consul_agent_addr = '127.0.0.1';
        }
        if ($consul_agent_addr == '127.0.0.1') {     // 启用内置consul
            $newConfig['bind_addr'] = getBindIp();
        } else {
            $newConfig['bind_addr'] = $consul_agent_addr;
        }

        if (array_key_exists('services', $config)) {
            foreach ($config['services'] as $service) {
                list($service_name, $service_port) = explode(":", $service);
                $service_port = (int)$service_port;
                $port_type = get_instance()->portManager->getPortType($service_port);
                switch ($port_type) {
                    case PortManager::SOCK_TCP:
                    case PortManager::SOCK_TCP6:
                        $newConfig['services'][] = [
                            'id' => "Tcp_$service_name",
                            'name' => $service_name,
                            // Modify by hb on 2017-12-21
                            //'address' => getBindIp(),
                            'address' => $this->getServiceBindIp(),
                            'port' => $service_port,
                            //'tags' => ['tcp'],
                            'tag' => $this->getServiceTag($service, "tcp"),
                            'check' => [
                                'name' => 'status',
                                'tcp' => $this->getServiceBindIp().":$service_port",
                                'interval' => "10s",
                                'timeout' => "1s"
                            ]];
                        break;
                    case PortManager::SOCK_HTTP:
                        $newConfig['services'][] = [
                            'id' => "Http_$service_name",
                            'name' => $service_name,
                            // Modify by hb on 2017-12-21
                            //'address' => getBindIp(),
                            'address' => $this->getServiceBindIp(),
                            'port' => $service_port,
                            'tags' => ['http'],
                            //'tag' => $this->getServiceTag($service, "http"),
                            'check' => [
                                'name' => 'status',
                                //'http' => "http://localhost:$service_port/$service_name/" . ConsulHelp::HEALTH,
                                'http' => "http://".$this->getServiceBindIp().":$service_port/$service_name/" . ConsulHelp::HEALTH,
                                'interval' => "10s",
                                'timeout' => "1s"
                            ]];
                        break;
                }
            }
        }
        file_put_contents(BIN_DIR . "/exec/consul.d/consul_config.json", json_encode($newConfig));
    }

    /**
     * 优先从docker环境变量获取service绑定IP
     * @return string
     * Add by hb on 2017-12-22
     */
    public function getServiceBindIp()
    {
        $env_SD_BIND_ADDR = getenv("SD_SERVICE_BIND_ADDR");
        if (!empty($env_SD_BIND_ADDR)) {
            return $env_SD_BIND_ADDR;
        } else {
            return getBindIp();
        }
    }

    /**
     * TODO: 优先从docker环境变量获取service的外部映射port
     * @return string
     * Add by hb on 2017-12-22
     */
    public function mapServiceBindPort($service_port)
    {
        // TODO: 如何获取映射关系？
        return $service_port;
    }

    public function getServiceTag($service, $base_tag)
    {
        $full_tag = $base_tag;
        $ext_tag = get_instance()->config->get("consul.$service.tag");
        if (isset($ext_tag)) {
            $full_tag = $full_tag.", ".$ext_tag;
        }
        //$full_tag = "http, Desc:授权用户API服务, Author:sun@wsd, Ver:1.0.0, PubTime: 2017-12-22 11:26:00";
        return $full_tag;
    }
}